package com.xianggu.trafficLimiter.impl;

import com.xianggu.trafficLimiter.TrafficLimiter;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author chengjy
 * @date 2025/3/25
 */

public class LeakyBucketLimiter implements TrafficLimiter {

    private final AtomicLong timeStamp = new AtomicLong(System.currentTimeMillis());
    private final long capacity; // 桶子的容量
    private final long rate;     // 水漏出的速度(每秒系统能处理的请求数)
    private final AtomicLong water = new AtomicLong(0); // 桶子中当前水量（当前积累的请求数）


    public LeakyBucketLimiter(long capacity, long rate) {
        if (capacity <= 0 || rate <= 0) {
            throw new IllegalArgumentException("Capacity and rate must be positive values.");
        }
        this.capacity = capacity;
        this.rate = rate;
    }

    @Override
    public boolean limit() {
        try {
            long now = System.currentTimeMillis();
            long elapsed = now - timeStamp.getAndSet(now);// 上次调用时间-当前时间 = 上次请求距今时间
            if (elapsed < 0) {
                // 防止系统时间被回拨导致计算错误
                return true;
            }

            long currentWater = water.get();
            long leakedWater = Math.max(0, elapsed * rate / 1000); // 计算漏掉的水量
            long updatedWater = Math.max(0, currentWater - leakedWater);
            System.out.println("上次请求距今时间： "+elapsed+ " leakedWater ："+ leakedWater +" 当前水量：" + updatedWater );
            if ((updatedWater + 1) <= capacity) {
                // 如果还有余量，允许请求并增加水量
                water.set(updatedWater + 1);
                return false;
            } else {
                // 水桶已满，拒绝请求
                water.set(updatedWater); // 更新水量以防止溢出
                return true;
            }
        } catch (Exception e) {
            // 异常处理，避免因系统时间或其他问题导致程序崩溃
            e.printStackTrace();
            return true;
        }
    }
}
